home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the 3D Game Programming Gurus / gurus.iso / DirectX / dx9sdkcp.exe / SDK (C++) / Bin / DXUtils / Visual Studio 6.0 Wizards / Source Code / Template / dmutil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-11-12  |  33.5 KB  |  976 lines

  1. //-----------------------------------------------------------------------------
  2. // File: DMUtil.cpp
  3. //
  4. // Desc: DirectMusic framework classes for playing DirectMusic segments and
  5. //       DirectMusic scripts. Feel free to use this class as a starting point 
  6. //       for adding extra functionality.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. $$IF(DLG)
  10. #include "stdafx.h"
  11. $$ENDIF
  12. #include <dmusicc.h>
  13. #include <dmusici.h>
  14. #include <dsound.h>
  15. #include <dxerr9.h>
  16. #include "DMUtil.h"
  17. #include "DXUtil.h"
  18.  
  19.  
  20.  
  21.  
  22. //-----------------------------------------------------------------------------
  23. // Name: CMusicManager::CMusicManager()
  24. // Desc: Constructs the class
  25. //-----------------------------------------------------------------------------
  26. CMusicManager::CMusicManager()
  27. {
  28.     m_pLoader       = NULL;
  29.     m_pPerformance  = NULL;
  30.     m_pDSListener   = NULL;
  31.     
  32.     // Initialize COM
  33.     HRESULT hr = CoInitialize(NULL);
  34.     m_bCleanupCOM = SUCCEEDED(hr);
  35. }
  36.  
  37.  
  38.  
  39.  
  40. //-----------------------------------------------------------------------------
  41. // Name: CMusicManager::~CMusicManager()
  42. // Desc: Destroys the class
  43. //-----------------------------------------------------------------------------
  44. CMusicManager::~CMusicManager()
  45. {
  46.     SAFE_RELEASE( m_pLoader ); 
  47.     SAFE_RELEASE( m_pDSListener );
  48.  
  49.     if( m_pPerformance )
  50.     {
  51.         // If there is any music playing, stop it.
  52.         m_pPerformance->Stop( NULL, NULL, 0, 0 );
  53.         m_pPerformance->CloseDown();
  54.  
  55.         SAFE_RELEASE( m_pPerformance );
  56.     }
  57.  
  58.     if( m_bCleanupCOM )
  59.         CoUninitialize();
  60. }
  61.  
  62.  
  63.  
  64.  
  65. //-----------------------------------------------------------------------------
  66. // Name: CMusicManager::Initialize()
  67. // Desc: Inits DirectMusic using a standard audio path
  68. //-----------------------------------------------------------------------------
  69. HRESULT CMusicManager::Initialize( HWND hWnd, DWORD dwPChannels, DWORD dwDefaultPathType, LPDIRECTSOUND pDS )
  70. {
  71.     HRESULT hr;
  72.     IDirectSound** ppDirectSound;
  73.  
  74.     if( pDS )
  75.         ppDirectSound = &pDS;
  76.     else
  77.         ppDirectSound = NULL;
  78.  
  79.     // Create loader object
  80.     if( FAILED( hr = CoCreateInstance( CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, 
  81.                                        IID_IDirectMusicLoader8, (void**)&m_pLoader ) ) )
  82.         return DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr );
  83.  
  84.     // Create performance object
  85.     if( FAILED( hr = CoCreateInstance( CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC, 
  86.                                        IID_IDirectMusicPerformance8, (void**)&m_pPerformance ) ) )
  87.         return DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr );
  88.  
  89.     // Initialize the performance with the standard audio path.
  90.     // This initializes both DirectMusic and DirectSound and 
  91.     // sets up the synthesizer. Typcially its easist to use an 
  92.     // audio path for playing music and sound effects.
  93.     if( FAILED( hr = m_pPerformance->InitAudio( NULL, ppDirectSound, hWnd, dwDefaultPathType, 
  94.                                                 dwPChannels, DMUS_AUDIOF_ALL, NULL ) ) )
  95.     {
  96.         if( hr == DSERR_NODRIVER )
  97.         {
  98.             DXTRACE( TEXT("Warning: No sound card found\n") );
  99.             return hr;
  100.         }
  101.  
  102.         return DXTRACE_ERR_MSGBOX( TEXT("InitAudio"), hr );
  103.     }
  104.  
  105.     // Get the listener from the in the default audio path.
  106.     IDirectMusicAudioPath8* pAudioPath = GetDefaultAudioPath();
  107.     if( pAudioPath ) // might be NULL if dwDefaultPathType == 0
  108.     {
  109.         if( SUCCEEDED( hr = pAudioPath->GetObjectInPath( 0, DMUS_PATH_PRIMARY_BUFFER, 0,
  110.                                                         GUID_NULL, 0, IID_IDirectSound3DListener, 
  111.                                                         (LPVOID*) &m_pDSListener ) ) )
  112.         {
  113.             // Get listener parameters
  114.             m_dsListenerParams.dwSize = sizeof(DS3DLISTENER);
  115.             m_pDSListener->GetAllParameters( &m_dsListenerParams );
  116.         }
  117.     }
  118.  
  119.     return S_OK;
  120. }
  121.  
  122.  
  123.  
  124.  
  125. //-----------------------------------------------------------------------------
  126. // Name: CMusicManager::SetSearchDirectory()
  127. // Desc: Sets the search directory.  If not called, the current working
  128. //       directory is used to load content.
  129. //-----------------------------------------------------------------------------
  130. HRESULT CMusicManager::SetSearchDirectory( const TCHAR* strMediaPath )
  131. {
  132.     if( NULL == m_pLoader )
  133.         return E_UNEXPECTED;
  134.     if( NULL == strMediaPath )
  135.         return E_INVALIDARG;
  136.  
  137.     // DMusic only takes wide strings
  138.     WCHAR wstrMediaPath[MAX_PATH];
  139.     DXUtil_ConvertGenericStringToWideCb( wstrMediaPath, strMediaPath, sizeof(wstrMediaPath) );
  140.  
  141.     return m_pLoader->SetSearchDirectory( GUID_DirectMusicAllTypes, 
  142.                                           wstrMediaPath, FALSE );
  143.  
  144. }
  145.  
  146.  
  147.  
  148.  
  149. //-----------------------------------------------------------------------------
  150. // Name: CMusicManager::GetDefaultAudioPath()
  151. // Desc: 
  152. //-----------------------------------------------------------------------------
  153. IDirectMusicAudioPath8* CMusicManager::GetDefaultAudioPath()
  154. {
  155.     IDirectMusicAudioPath8* pAudioPath = NULL;
  156.     if( NULL == m_pPerformance )
  157.         return NULL;
  158.  
  159.     m_pPerformance->GetDefaultAudioPath( &pAudioPath );
  160.     return pAudioPath;
  161. }
  162.  
  163.  
  164.  
  165.  
  166. //-----------------------------------------------------------------------------
  167. // Name: CMusicManager::CollectGarbage()
  168. // Desc: Tells the loader to cleanup any garbage from previously 
  169. //       released objects.
  170. //-----------------------------------------------------------------------------
  171. VOID CMusicManager::CollectGarbage()
  172. {
  173.     if( m_pLoader )
  174.         m_pLoader->CollectGarbage();
  175. }
  176.  
  177.  
  178.  
  179.  
  180. //-----------------------------------------------------------------------------
  181. // Name: CMusicManager::StopAll()
  182. // Desc: Stops all segments.  Also simply calling Stop() on the segment won't 
  183. //       stop any MIDI sustain pedals, but calling StopAll() will.
  184. //-----------------------------------------------------------------------------
  185. VOID CMusicManager::StopAll()
  186. {
  187.     if( m_pPerformance )
  188.         m_pPerformance->Stop( NULL, NULL, 0, 0 );
  189. }
  190.  
  191.  
  192.  
  193. //-----------------------------------------------------------------------------
  194. // Name: CMusicManager::CreateSegmentFromFile()
  195. // Desc: 
  196. //-----------------------------------------------------------------------------
  197. HRESULT CMusicManager::CreateSegmentFromFile( CMusicSegment** ppSegment, 
  198.                                               TCHAR* strFileName, 
  199.                                               BOOL bDownloadNow,
  200.                                               BOOL bIsMidiFile )
  201. {
  202.     HRESULT               hr;
  203.     IDirectMusicSegment8* pSegment = NULL;
  204.  
  205.     // DMusic only takes wide strings
  206.     WCHAR wstrFileName[MAX_PATH];
  207.     DXUtil_ConvertGenericStringToWideCb( wstrFileName, strFileName, sizeof(wstrFileName) );
  208.  
  209.     if ( FAILED( hr = m_pLoader->LoadObjectFromFile( CLSID_DirectMusicSegment,
  210.                                                      IID_IDirectMusicSegment8,
  211.                                                      wstrFileName,
  212.                                                      (LPVOID*) &pSegment ) ) )
  213.     {
  214.         if( hr == DMUS_E_LOADER_FAILEDOPEN )
  215.             return hr;
  216.         return DXTRACE_ERR_MSGBOX( TEXT("LoadObjectFromFile"), hr );
  217.     }
  218.  
  219.     *ppSegment = new CMusicSegment( m_pPerformance, m_pLoader, pSegment );
  220.     if (!*ppSegment)
  221.         return E_OUTOFMEMORY;
  222.  
  223.     if( bIsMidiFile )
  224.     {
  225.         if( FAILED( hr = pSegment->SetParam( GUID_StandardMIDIFile, 
  226.                                              0xFFFFFFFF, 0, 0, NULL ) ) )
  227.             return DXTRACE_ERR_MSGBOX( TEXT("SetParam"), hr );
  228.     }
  229.  
  230.     if( bDownloadNow )
  231.     {
  232.         if( FAILED( hr = (*ppSegment)->Download() ) )
  233.             return DXTRACE_ERR_MSGBOX( TEXT("Download"), hr );
  234.     }
  235.  
  236.     return S_OK;
  237. }
  238.  
  239.  
  240.  
  241.  
  242. //-----------------------------------------------------------------------------
  243. // Name: CMusicManager::CreateSegmentFromResource()
  244. // Desc: 
  245. //-----------------------------------------------------------------------------
  246. HRESULT CMusicManager::CreateSegmentFromResource( CMusicSegment** ppSegment, 
  247.                                                   TCHAR* strResource,
  248.                                                   TCHAR* strResourceType,
  249.                                                   BOOL bDownloadNow,
  250.                                                   BOOL bIsMidiFile )
  251. {
  252.     HRESULT               hr;
  253.     IDirectMusicSegment8* pSegment      = NULL;
  254.     HRSRC                 hres          = NULL;
  255.     void*                 pMem          = NULL;
  256.     DWORD                 dwSize        = 0;
  257.     DMUS_OBJECTDESC       objdesc;
  258.  
  259.     // Find the resource
  260.     hres = FindResource( NULL,strResource,strResourceType );
  261.     if( NULL == hres ) 
  262.         return E_FAIL;
  263.  
  264.     // Load the resource
  265.     pMem = (void*)LoadResource( NULL, hres );
  266.     if( NULL == pMem ) 
  267.         return E_FAIL;
  268.  
  269.     // Store the size of the resource
  270.     dwSize = SizeofResource( NULL, hres ); 
  271.     
  272.     // Set up our object description 
  273.     ZeroMemory(&objdesc,sizeof(DMUS_OBJECTDESC));
  274.     objdesc.dwSize = sizeof(DMUS_OBJECTDESC);
  275.     objdesc.dwValidData = DMUS_OBJ_MEMORY | DMUS_OBJ_CLASS;
  276.     objdesc.guidClass = CLSID_DirectMusicSegment;
  277.     objdesc.llMemLength =(LONGLONG)dwSize;
  278.     objdesc.pbMemData = (BYTE*)pMem;
  279.     
  280.     if (FAILED ( hr = m_pLoader->GetObject( &objdesc,
  281.                                             IID_IDirectMusicSegment8,
  282.                                             (void**)&pSegment ) ) )
  283.     {
  284.         if( hr == DMUS_E_LOADER_FAILEDOPEN )
  285.             return hr;
  286.         return DXTRACE_ERR_MSGBOX( TEXT("LoadObjectFromFile"), hr );
  287.     }
  288.  
  289.     *ppSegment = new CMusicSegment( m_pPerformance, m_pLoader, pSegment );
  290.     if( NULL == *ppSegment )
  291.         return E_OUTOFMEMORY;
  292.  
  293.     if( bIsMidiFile )
  294.     {
  295.         // Do this to make sure that the default General MIDI set 
  296.         // is connected appropriately to the MIDI file and 
  297.         // all instruments sound correct.                  
  298.         if( FAILED( hr = pSegment->SetParam( GUID_StandardMIDIFile, 
  299.                                              0xFFFFFFFF, 0, 0, NULL ) ) )
  300.             return DXTRACE_ERR_MSGBOX( TEXT("SetParam"), hr );
  301.     }
  302.  
  303.     if( bDownloadNow )
  304.     {
  305.         // The segment needs to be download first before playing.  
  306.         // However, some apps may want to wait before calling this 
  307.         // to because the download allocates memory for the 
  308.         // instruments. The more instruments currently downloaded, 
  309.         // the more memory is in use by the synthesizer.
  310.         if( FAILED( hr = (*ppSegment)->Download() ) )
  311.             return DXTRACE_ERR_MSGBOX( TEXT("Download"), hr );
  312.     }
  313.  
  314.     return S_OK;
  315. }
  316.  
  317.  
  318.  
  319.  
  320. //-----------------------------------------------------------------------------
  321. // Name: CMusicManager::Create3DSegmentFromFile()
  322. // Desc: 
  323. //-----------------------------------------------------------------------------
  324. HRESULT CMusicManager::Create3DSegmentFromFile( C3DMusicSegment** pp3DMusicSegment, 
  325.                                               TCHAR* strFileName, 
  326.                                               BOOL bDownloadNow,
  327.                                               BOOL bIsMidiFile,
  328.                                               IDirectMusicAudioPath8* p3DAudioPath )
  329. {
  330.     HRESULT               hr;
  331.     IDirectMusicSegment8* pSegment = NULL;
  332.  
  333.     // DMusic only takes wide strings
  334.     WCHAR wstrFileName[MAX_PATH];
  335.     DXUtil_ConvertGenericStringToWideCb( wstrFileName, strFileName, sizeof(wstrFileName) );
  336.  
  337.     if ( FAILED( hr = m_pLoader->LoadObjectFromFile( CLSID_DirectMusicSegment,
  338.                                                      IID_IDirectMusicSegment8,
  339.                                                      wstrFileName,
  340.                                                      (LPVOID*) &pSegment ) ) )
  341.     {
  342.         if( hr == DMUS_E_LOADER_FAILEDOPEN )
  343.             return hr;
  344.         return DXTRACE_ERR( TEXT("LoadObjectFromFile"), hr );
  345.     }
  346.  
  347.     *pp3DMusicSegment = new C3DMusicSegment( m_pPerformance, m_pLoader, pSegment, p3DAudioPath );
  348.     if (!*pp3DMusicSegment)
  349.         return E_OUTOFMEMORY;
  350.  
  351.     if( FAILED( hr = (*pp3DMusicSegment)->Init() ) ) 
  352.         return DXTRACE_ERR( TEXT("SetParam"), hr );
  353.  
  354.     if( bIsMidiFile )
  355.     {
  356.         if( FAILED( hr = pSegment->SetParam( GUID_StandardMIDIFile, 
  357.                                              0xFFFFFFFF, 0, 0, NULL ) ) )
  358.             return DXTRACE_ERR( TEXT("SetParam"), hr );
  359.     }
  360.  
  361.     if( bDownloadNow )
  362.     {
  363.         if( FAILED( hr = (*pp3DMusicSegment)->Download() ) )
  364.             return DXTRACE_ERR( TEXT("Download"), hr );
  365.     }
  366.  
  367.     return S_OK;
  368. }
  369.  
  370.  
  371.  
  372.  
  373. //-----------------------------------------------------------------------------
  374. // Name: CMusicManager::CreateScriptFromFile()
  375. // Desc: 
  376. //-----------------------------------------------------------------------------
  377. HRESULT CMusicManager::CreateScriptFromFile( CMusicScript** ppScript, 
  378.                                              TCHAR* strFileName )
  379. {
  380.     HRESULT               hr;
  381.     IDirectMusicScript* pScript = NULL;
  382.  
  383.     // DMusic only takes wide strings
  384.     WCHAR wstrFileName[MAX_PATH];
  385.     DXUtil_ConvertGenericStringToWideCb( wstrFileName, strFileName, sizeof(wstrFileName) );
  386.     
  387.     if ( FAILED( hr = m_pLoader->LoadObjectFromFile( CLSID_DirectMusicScript,
  388.                                                      IID_IDirectMusicScript8,
  389.                                                      wstrFileName,
  390.                                                      (LPVOID*) &pScript ) ) )
  391.         return DXTRACE_ERR( TEXT("LoadObjectFromFile"), hr );
  392.  
  393.     if ( FAILED( hr = pScript->Init( m_pPerformance, NULL ) ) )
  394.         return DXTRACE_ERR_MSGBOX( TEXT("Init"), hr );
  395.  
  396.     *ppScript = new CMusicScript( m_pPerformance, m_pLoader, pScript );
  397.     if (!*ppScript)
  398.         return E_OUTOFMEMORY;
  399.  
  400.     return hr;
  401. }
  402.  
  403.  
  404.  
  405.  
  406. //-----------------------------------------------------------------------------
  407. // Name: CMusicManager::CreateChordMapFromFile()
  408. // Desc: 
  409. //-----------------------------------------------------------------------------
  410. HRESULT CMusicManager::CreateChordMapFromFile( IDirectMusicChordMap8** ppChordMap, 
  411.                                                TCHAR* strFileName )
  412. {
  413.     // DMusic only takes wide strings
  414.     WCHAR wstrFileName[MAX_PATH];
  415.     DXUtil_ConvertGenericStringToWideCb( wstrFileName, strFileName, sizeof(wstrFileName) );
  416.  
  417.     return m_pLoader->LoadObjectFromFile( CLSID_DirectMusicChordMap,
  418.                                           IID_IDirectMusicChordMap8,
  419.                                           wstrFileName, (LPVOID*) ppChordMap );
  420. }
  421.  
  422.  
  423.  
  424.  
  425. //-----------------------------------------------------------------------------
  426. // Name: CMusicManager::CreateChordMapFromFile()
  427. // Desc: 
  428. //-----------------------------------------------------------------------------
  429. HRESULT CMusicManager::CreateStyleFromFile( IDirectMusicStyle8** ppStyle, 
  430.                                             TCHAR* strFileName )
  431. {
  432.     // DMusic only takes wide strings
  433.     WCHAR wstrFileName[MAX_PATH];
  434.     DXUtil_ConvertGenericStringToWideCb( wstrFileName, strFileName, sizeof(wstrFileName) );
  435.  
  436.     return m_pLoader->LoadObjectFromFile( CLSID_DirectMusicStyle,
  437.                                           IID_IDirectMusicStyle8,
  438.                                           wstrFileName, (LPVOID*) ppStyle );
  439. }
  440.  
  441.  
  442.  
  443.  
  444. //-----------------------------------------------------------------------------
  445. // Name: CMusicManager::GetMotifFromStyle()
  446. // Desc: 
  447. //-----------------------------------------------------------------------------
  448. HRESULT CMusicManager::GetMotifFromStyle( IDirectMusicSegment8** ppMotif8, 
  449.                                           TCHAR* strStyle, TCHAR* strMotif )
  450. {       
  451.     UNREFERENCED_PARAMETER( strMotif );
  452.     
  453.     HRESULT              hr;
  454.     IDirectMusicStyle8*  pStyle = NULL;
  455.     IDirectMusicSegment* pMotif = NULL;
  456.  
  457.     if( FAILED( hr = CreateStyleFromFile( &pStyle, strStyle ) ) )
  458.         return DXTRACE_ERR_MSGBOX( TEXT("CreateStyleFromFile"), hr );
  459.  
  460.     if( pStyle )
  461.     {
  462.         // DMusic only takes wide strings
  463.         WCHAR wstrMotif[MAX_PATH];
  464.         DXUtil_ConvertGenericStringToWideCb( wstrMotif, strStyle, sizeof(wstrMotif) );
  465.  
  466.         hr = pStyle->GetMotif( wstrMotif, &pMotif );
  467.         SAFE_RELEASE( pStyle );
  468.  
  469.         if( FAILED( hr ) )
  470.             return DXTRACE_ERR_MSGBOX( TEXT("GetMotif"), hr );
  471.  
  472.         pMotif->QueryInterface( IID_IDirectMusicSegment8, (LPVOID*) ppMotif8 );
  473.     }
  474.  
  475.     return S_OK;
  476. }
  477.  
  478.  
  479.  
  480.  
  481. //-----------------------------------------------------------------------------
  482. // Name: Set3DParameters
  483. // Desc: 
  484. //-----------------------------------------------------------------------------
  485. VOID CMusicManager::Set3DParameters( FLOAT fDistanceFactor, FLOAT fDopplerFactor, FLOAT fRolloffFactor )
  486. {
  487.     m_dsListenerParams.flDistanceFactor = fDistanceFactor;
  488.     m_dsListenerParams.flDopplerFactor = fDopplerFactor;
  489.     m_dsListenerParams.flRolloffFactor = fRolloffFactor;
  490.  
  491.     if( m_pDSListener )
  492.         m_pDSListener->SetAllParameters( &m_dsListenerParams, DS3D_IMMEDIATE );
  493. }
  494.  
  495.  
  496.  
  497.  
  498. //-----------------------------------------------------------------------------
  499. // Name: CMusicSegment::CMusicSegment()
  500. // Desc: Constructs the class
  501. //-----------------------------------------------------------------------------
  502. CMusicSegment::CMusicSegment( IDirectMusicPerformance8* pPerformance, 
  503.                               IDirectMusicLoader8*      pLoader,
  504.                               IDirectMusicSegment8*     pSegment )
  505. {
  506.     m_pPerformance          = pPerformance;
  507.     m_pLoader               = pLoader;
  508.     m_pSegment              = pSegment;
  509.     m_pEmbeddedAudioPath    = NULL;
  510.     m_bDownloaded           = FALSE;
  511.     
  512.     // Try to pull out an audio path from the segment itself if there is one.
  513.     // This embedded audio path will be used instead of the default
  514.     // audio path if the app doesn't wish to use an overriding audio path.
  515.     IUnknown* pConfig = NULL;
  516.     if( SUCCEEDED( m_pSegment->GetAudioPathConfig( &pConfig ) ) )
  517.     {
  518.         m_pPerformance->CreateAudioPath( pConfig, TRUE, &m_pEmbeddedAudioPath );
  519.         SAFE_RELEASE( pConfig );
  520.     } 
  521.  
  522. }
  523.  
  524.  
  525.  
  526.  
  527. //-----------------------------------------------------------------------------
  528. // Name: CMusicSegment::~CMusicSegment()
  529. // Desc: Destroys the class
  530. //-----------------------------------------------------------------------------
  531. CMusicSegment::~CMusicSegment()
  532. {
  533.     if( m_pSegment )
  534.     {
  535.         // Tell the loader that this object should now be released
  536.         if( m_pLoader )
  537.             m_pLoader->ReleaseObjectByUnknown( m_pSegment );
  538.  
  539.         if( m_bDownloaded )
  540.         {
  541.             if( m_pEmbeddedAudioPath )
  542.                 m_pSegment->Unload( m_pEmbeddedAudioPath );
  543.             else
  544.                 m_pSegment->Unload( m_pPerformance );
  545.         }
  546.  
  547.         SAFE_RELEASE( m_pEmbeddedAudioPath ); 
  548.         SAFE_RELEASE( m_pSegment ); 
  549.     }
  550.  
  551.     m_pPerformance = NULL;
  552. }
  553.  
  554.  
  555.  
  556.  
  557. //-----------------------------------------------------------------------------
  558. // Name: CMusicSegment::Play()
  559. // Desc: Plays the sound using voice management flags.  Pass in DSBPLAY_LOOPING
  560. //       in the dwFlags to loop the sound
  561. //-----------------------------------------------------------------------------
  562. HRESULT CMusicSegment::Play( DWORD dwFlags, IDirectMusicAudioPath8* pAudioPath )
  563. {
  564.     if( m_pSegment == NULL || m_pPerformance == NULL )
  565.         return CO_E_NOTINITIALIZED;
  566.  
  567.     if( !m_bDownloaded )
  568.         return E_FAIL;
  569.  
  570.     // If an audio path was passed in then use it, otherwise
  571.     // use the embedded audio path if there was one.
  572.     if( pAudioPath == NULL && m_pEmbeddedAudioPath != NULL )
  573.         pAudioPath = m_pEmbeddedAudioPath;
  574.         
  575.     // If pAudioPath is NULL then this plays on the default audio path.
  576.     return m_pPerformance->PlaySegmentEx( m_pSegment, 0, NULL, dwFlags, 
  577.                                           0, 0, NULL, pAudioPath );
  578. }
  579.  
  580.  
  581.  
  582.  
  583.  
  584. //-----------------------------------------------------------------------------
  585. // Name: CMusicSegment::Download()
  586. // Desc: 
  587. //-----------------------------------------------------------------------------
  588. HRESULT CMusicSegment::Download( IDirectMusicAudioPath8* pAudioPath )
  589. {
  590.     HRESULT hr;
  591.     
  592.     if( m_pSegment == NULL )
  593.         return CO_E_NOTINITIALIZED;
  594.  
  595.     // If no audio path was passed in, then download
  596.     // to the embedded audio path if it exists 
  597.     // else download to the performance
  598.     if( pAudioPath == NULL )
  599.     {
  600.         if( m_pEmbeddedAudioPath )
  601.             hr = m_pSegment->Download( m_pEmbeddedAudioPath );
  602.         else    
  603.             hr = m_pSegment->Download( m_pPerformance );
  604.     }
  605.     else
  606.     {
  607.         hr = m_pSegment->Download( pAudioPath );
  608.     }
  609.     
  610.     if ( SUCCEEDED( hr ) )
  611.         m_bDownloaded = TRUE;
  612.         
  613.     return hr;
  614. }
  615.  
  616.  
  617.  
  618.  
  619. //-----------------------------------------------------------------------------
  620. // Name: CMusicSegment::Unload()
  621. // Desc: 
  622. //-----------------------------------------------------------------------------
  623. HRESULT CMusicSegment::Unload( IDirectMusicAudioPath8* pAudioPath )
  624. {
  625.     HRESULT hr;
  626.     
  627.     if( m_pSegment == NULL )
  628.         return CO_E_NOTINITIALIZED;
  629.  
  630.     // If no audio path was passed in, then unload 
  631.     // from the embedded audio path if it exists 
  632.     // else unload from the performance
  633.     if( pAudioPath == NULL )
  634.     {
  635.         if( m_pEmbeddedAudioPath )
  636.             hr = m_pSegment->Unload( m_pEmbeddedAudioPath );
  637.         else    
  638.             hr = m_pSegment->Unload( m_pPerformance );
  639.     }
  640.     else
  641.     {
  642.         hr = m_pSegment->Unload( pAudioPath );
  643.     }
  644.         
  645.     if ( SUCCEEDED( hr ) )
  646.         m_bDownloaded = FALSE;
  647.  
  648.     return hr;
  649. }
  650.  
  651.  
  652.  
  653.  
  654. //-----------------------------------------------------------------------------
  655. // Name: CMusicSegment::IsPlaying()
  656. // Desc: 
  657. //-----------------------------------------------------------------------------
  658. BOOL CMusicSegment::IsPlaying()
  659. {
  660.     if( m_pSegment == NULL || m_pPerformance == NULL )
  661.         return FALSE;
  662.  
  663.     return ( m_pPerformance->IsPlaying( m_pSegment, NULL ) == S_OK );
  664. }
  665.  
  666.  
  667.  
  668.  
  669. //-----------------------------------------------------------------------------
  670. // Name: CMusicSegment::Stop()
  671. // Desc: Stops the sound from playing
  672. //-----------------------------------------------------------------------------
  673. HRESULT CMusicSegment::Stop( DWORD dwFlags )
  674. {
  675.     if( m_pSegment == NULL || m_pPerformance == NULL )
  676.         return CO_E_NOTINITIALIZED;
  677.  
  678.     return m_pPerformance->Stop( m_pSegment, NULL, 0, dwFlags );;
  679. }
  680.  
  681.  
  682.  
  683.  
  684. //-----------------------------------------------------------------------------
  685. // Name: CMusicSegment::SetRepeats()
  686. // Desc: 
  687. //-----------------------------------------------------------------------------
  688. HRESULT CMusicSegment::SetRepeats( DWORD dwRepeats )
  689. {
  690.     if( m_pSegment == NULL )
  691.         return CO_E_NOTINITIALIZED;
  692.  
  693.     return m_pSegment->SetRepeats( dwRepeats );
  694. }
  695.  
  696.  
  697.  
  698.  
  699. //-----------------------------------------------------------------------------
  700. // Name: CMusicSegment::GetStyle()
  701. // Desc: 
  702. //-----------------------------------------------------------------------------
  703. HRESULT CMusicSegment::GetStyle( IDirectMusicStyle8** ppStyle, DWORD dwStyleIndex )
  704. {
  705.     // Get the Style from the Segment by calling the Segment's GetData() with
  706.     // the data type GUID_StyleTrackStyle. 0xffffffff indicates to look at
  707.     // tracks in all TrackGroups in the segment. The first 0 indicates to
  708.     // retrieve the Style from the first Track  in the indicated TrackGroup.
  709.     // The second 0 indicates to retrieve the Style from the beginning of the
  710.     // segment, i.e. time 0 in Segment time. If this Segment was loaded from a
  711.     // section file, there is only one Style and it is at time 0.
  712.     return m_pSegment->GetParam( GUID_IDirectMusicStyle, 0xffffffff, dwStyleIndex, 
  713.                                  0, NULL, (VOID*)ppStyle );
  714. }
  715.  
  716.  
  717.  
  718.  
  719.  
  720. //-----------------------------------------------------------------------------
  721. // Name: C3DMusicSegment::C3DMusicSegment()
  722. // Desc: Constructs the class
  723. //-----------------------------------------------------------------------------
  724. C3DMusicSegment::C3DMusicSegment( IDirectMusicPerformance8* pPerformance, 
  725.                               IDirectMusicLoader8*      pLoader,
  726.                               IDirectMusicSegment8*     pSegment,
  727.                               IDirectMusicAudioPath8* pAudioPath ) :
  728.     CMusicSegment( pPerformance, pLoader, pSegment )
  729. {
  730.     m_p3DAudioPath      = pAudioPath;
  731.     m_pDS3DBuffer       = NULL;
  732.     m_bDeferSettings    = FALSE;
  733.     m_bCleanupAudioPath = FALSE;
  734. }
  735.  
  736.  
  737.  
  738.  
  739. //-----------------------------------------------------------------------------
  740. // Name: C3DMusicSegment::~C3DMusicSegment()
  741. // Desc: Destroys the class
  742. //-----------------------------------------------------------------------------
  743. C3DMusicSegment::~C3DMusicSegment()
  744. {
  745.     SAFE_RELEASE( m_pDS3DBuffer );
  746.     if( m_bCleanupAudioPath )
  747.         SAFE_RELEASE( m_p3DAudioPath );
  748. }
  749.  
  750.  
  751.  
  752.  
  753. //-----------------------------------------------------------------------------
  754. // Name: Init()
  755. // Desc: 
  756. //-----------------------------------------------------------------------------
  757. HRESULT C3DMusicSegment::Init()
  758. {
  759.     HRESULT hr;
  760.  
  761.     if( NULL == m_p3DAudioPath )
  762.     {
  763.         // Create a 3D audiopath with a 3d buffer.
  764.         // We can then play all segments into this buffer and directly control its
  765.         // 3D parameters.
  766.         if( FAILED( hr = m_pPerformance->CreateStandardAudioPath( DMUS_APATH_DYNAMIC_3D, 
  767.                                                                 64, TRUE, &m_p3DAudioPath ) ) )
  768.             return DXTRACE_ERR( TEXT("CreateStandardAudioPath"), hr );
  769.         m_bCleanupAudioPath = TRUE;
  770.     }
  771.  
  772.     // Get the 3D buffer in the audio path.
  773.     if( FAILED( hr = m_p3DAudioPath->GetObjectInPath( 0, DMUS_PATH_BUFFER, 0,
  774.                                                       GUID_NULL, 0, IID_IDirectSound3DBuffer, 
  775.                                                       (LPVOID*) &m_pDS3DBuffer ) ) )
  776.         return DXTRACE_ERR( TEXT("GetObjectInPath"), hr );
  777.  
  778.     // Get the 3D buffer parameters
  779.     m_dsBufferParams.dwSize = sizeof(DS3DBUFFER);
  780.     m_pDS3DBuffer->GetAllParameters( &m_dsBufferParams );
  781.  
  782.     // Set new 3D buffer parameters
  783.     m_dsBufferParams.dwMode = DS3DMODE_HEADRELATIVE;
  784.     m_pDS3DBuffer->SetAllParameters( &m_dsBufferParams, DS3D_IMMEDIATE );
  785.    
  786.     return S_OK;
  787. }
  788.  
  789.  
  790.  
  791.  
  792. //-----------------------------------------------------------------------------
  793. // Name: Play
  794. // Desc: 
  795. //-----------------------------------------------------------------------------
  796. HRESULT C3DMusicSegment::Play( DWORD dwFlags, IDirectMusicAudioPath8* pAudioPath )
  797. {
  798.     if( pAudioPath ) 
  799.         return CMusicSegment::Play( dwFlags, pAudioPath );
  800.     else
  801.         return CMusicSegment::Play( dwFlags, m_p3DAudioPath );
  802. }
  803.  
  804.  
  805.  
  806.  
  807. //-----------------------------------------------------------------------------
  808. // Name: Set3DParameters
  809. // Desc: 
  810. //-----------------------------------------------------------------------------
  811. VOID C3DMusicSegment::Set3DParameters( FLOAT fMinDistance, FLOAT fMaxDistance )
  812. {
  813.     // Every change to 3-D sound buffer and listener settings causes 
  814.     // DirectSound to remix, at the expense of CPU cycles. 
  815.     // To minimize the performance impact of changing 3-D settings, 
  816.     // use the DS3D_DEFERRED flag in the dwApply parameter of any of 
  817.     // the IDirectSound3DListener or IDirectSound3DBuffer methods that 
  818.     // change 3-D settings. Then call the IDirectSound3DListener::CommitDeferredSettings 
  819.     // method to execute all of the deferred commands at once.
  820.     DWORD dwApplyFlag = ( m_bDeferSettings ) ? DS3D_DEFERRED : DS3D_IMMEDIATE;
  821.  
  822.     m_dsBufferParams.flMinDistance = fMinDistance;
  823.     m_dsBufferParams.flMaxDistance = fMaxDistance;
  824.  
  825.     if( m_pDS3DBuffer )
  826.         m_pDS3DBuffer->SetAllParameters( &m_dsBufferParams, dwApplyFlag );
  827. }
  828.  
  829.  
  830.  
  831.  
  832. //-----------------------------------------------------------------------------
  833. // Name: SetObjectProperties
  834. // Desc: 
  835. //-----------------------------------------------------------------------------
  836. VOID C3DMusicSegment::SetObjectProperties( D3DVECTOR* pvPosition, D3DVECTOR* pvVelocity )
  837. {
  838.     DWORD dwApplyFlag = ( m_bDeferSettings ) ? DS3D_DEFERRED : DS3D_IMMEDIATE;
  839.  
  840.     // Every change to 3-D sound buffer and listener settings causes 
  841.     // DirectSound to remix, at the expense of CPU cycles. 
  842.     // To minimize the performance impact of changing 3-D settings, 
  843.     // use the DS3D_DEFERRED flag in the dwApply parameter of any of 
  844.     // the IDirectSound3DListener or IDirectSound3DBuffer methods that 
  845.     // change 3-D settings. Then call the IDirectSound3DListener::CommitDeferredSettings 
  846.     // method to execute all of the deferred commands at once.
  847.     memcpy( &m_dsBufferParams.vPosition, pvPosition, sizeof(D3DVECTOR) );
  848.     memcpy( &m_dsBufferParams.vVelocity, pvVelocity, sizeof(D3DVECTOR) );
  849.  
  850.     if( m_pDS3DBuffer )
  851.     {
  852.         m_pDS3DBuffer->SetPosition( m_dsBufferParams.vPosition.x,
  853.                                     m_dsBufferParams.vPosition.y,
  854.                                     m_dsBufferParams.vPosition.z, dwApplyFlag );
  855.  
  856.         m_pDS3DBuffer->SetVelocity( m_dsBufferParams.vVelocity.x,
  857.                                     m_dsBufferParams.vVelocity.y,
  858.                                     m_dsBufferParams.vVelocity.z, dwApplyFlag );
  859.     }
  860. }
  861.  
  862.  
  863.  
  864. //-----------------------------------------------------------------------------
  865. // Name: CMusicScript::CMusicScript()
  866. // Desc: Constructs the class
  867. //-----------------------------------------------------------------------------
  868. CMusicScript::CMusicScript( IDirectMusicPerformance8* pPerformance, 
  869.                             IDirectMusicLoader8* pLoader,                   
  870.                             IDirectMusicScript8* pScript )
  871. {
  872.     m_pPerformance = pPerformance;
  873.     m_pLoader      = pLoader;
  874.     m_pScript      = pScript;
  875. }
  876.  
  877.  
  878.  
  879.  
  880. //-----------------------------------------------------------------------------
  881. // Name: CMusicScript::~CMusicScript()
  882. // Desc: Destroys the class
  883. //-----------------------------------------------------------------------------
  884. CMusicScript::~CMusicScript()
  885. {
  886.     if( m_pLoader )
  887.     {
  888.         // Tell the loader that this object should now be released
  889.         m_pLoader->ReleaseObjectByUnknown( m_pScript );
  890.         m_pLoader = NULL;
  891.     }
  892.  
  893.     SAFE_RELEASE( m_pScript ); 
  894.     m_pPerformance = NULL;
  895. }
  896.  
  897.  
  898.  
  899.  
  900. //-----------------------------------------------------------------------------
  901. // Name: CMusicScript::Play()
  902. // Desc: Calls a routine in the script
  903. //-----------------------------------------------------------------------------
  904. HRESULT CMusicScript::CallRoutine( TCHAR* strRoutine )
  905. {
  906.     // DMusic only takes wide strings
  907.     WCHAR wstrRoutine[MAX_PATH];
  908.     DXUtil_ConvertGenericStringToWideCb( wstrRoutine, strRoutine, sizeof(wstrRoutine) );
  909.  
  910.     return m_pScript->CallRoutine( wstrRoutine, NULL );
  911. }
  912.  
  913.  
  914.  
  915.  
  916. //-----------------------------------------------------------------------------
  917. // Name: CMusicScript::SetVariableNumber()
  918. // Desc: Sets the value of a variable in the script
  919. //-----------------------------------------------------------------------------
  920. HRESULT CMusicScript::SetVariableNumber( TCHAR* strVariable, LONG lValue )
  921. {
  922.     // DMusic only takes wide strings
  923.     WCHAR wstrVariable[MAX_PATH];
  924.     DXUtil_ConvertGenericStringToWideCb( wstrVariable, strVariable, sizeof(wstrVariable) );
  925.  
  926.     return m_pScript->SetVariableNumber( wstrVariable, lValue, NULL );
  927. }
  928.  
  929.  
  930.  
  931.  
  932. //-----------------------------------------------------------------------------
  933. // Name: CMusicScript::GetVariableNumber()
  934. // Desc: Gets the value of a variable in the script
  935. //-----------------------------------------------------------------------------
  936. HRESULT CMusicScript::GetVariableNumber( TCHAR* strVariable, LONG* plValue )
  937. {
  938.     // DMusic only takes wide strings
  939.     WCHAR wstrVariable[MAX_PATH];
  940.     DXUtil_ConvertGenericStringToWideCb( wstrVariable, strVariable, sizeof(wstrVariable) );
  941.  
  942.     return m_pScript->GetVariableNumber( wstrVariable, plValue, NULL );
  943. }
  944.  
  945.  
  946.  
  947. //-----------------------------------------------------------------------------
  948. // Name: CMusicScript::SetVariableObject()
  949. // Desc: Sets an object in the script
  950. //-----------------------------------------------------------------------------
  951. HRESULT CMusicScript::SetVariableObject( TCHAR* strVariable, IUnknown *punkValue )
  952. {
  953.     // DMusic only takes wide strings
  954.     WCHAR wstrVariable[MAX_PATH];
  955.     DXUtil_ConvertGenericStringToWideCb( wstrVariable, strVariable, sizeof(wstrVariable) );
  956.  
  957.     return m_pScript->SetVariableObject( wstrVariable, punkValue, NULL );
  958. }
  959.  
  960.  
  961.  
  962.  
  963. //-----------------------------------------------------------------------------
  964. // Name: CMusicScript::GetVariableObject()
  965. // Desc: Gets an object from the script
  966. //-----------------------------------------------------------------------------
  967. HRESULT CMusicScript::GetVariableObject( TCHAR* strVariable, REFIID riid, LPVOID FAR *ppv )
  968. {
  969.     // DMusic only takes wide strings
  970.     WCHAR wstrVariable[MAX_PATH];
  971.     DXUtil_ConvertGenericStringToWideCb( wstrVariable, strVariable, sizeof(wstrVariable) );
  972.  
  973.     return m_pScript->GetVariableObject( wstrVariable, riid, ppv, NULL );
  974. }
  975.  
  976.